package com.zyw.customcalendar.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;

import com.zyw.customcalendar.R;
import com.zyw.customcalendar.event.EventIndex;
import com.zyw.customcalendar.operation.CalendarDraw;

import de.greenrobot.event.EventBus;

/**
 * Created by zyw on 2017/9/19.
 */
public class VerticalSlideView extends FrameLayout {

    private View mSlideHeader;
    private View mSlideContent;
    //private ValueAnimator mScrollAnimation;

    public VerticalSlideView(Context context) {
        super(context);
        EventBus.getDefault().register(this);
    }

    public VerticalSlideView(Context context, AttributeSet attrs) {
        super(context, attrs);
        EventBus.getDefault().register(this);
    }

    public VerticalSlideView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        EventBus.getDefault().register(this);
    }

    private void startAnimation(int start, int end) {
        ValueAnimator mScrollAnimation = new ValueAnimator().ofInt(start, end);
        mScrollAnimation.setInterpolator(new DecelerateInterpolator());
        mScrollAnimation.setDuration(300);
        mScrollAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                int deltay = value - mLastScrollY;
                checkDrag(deltay);
                mLastScrollY = value;
            }
        });
        mScrollAnimation.start();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        android.util.Log.i("zyw","onFinishInflate 1");
        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mTouchSlop = configuration.getScaledTouchSlop();

        //mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
        //mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

        mSlideHeader = findViewById(R.id.calendar_layout);
        mSlideContent = findViewById(R.id.nest_scroll_view);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        EventBus.getDefault().unregister(this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mSlideHeaderHeight = mSlideHeader.getHeight();
        initLimitHeight();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        mSlideContent.layout(mSlideContent.getLeft(), mSlideContent.getTop() + mSlideHeaderHeight,
                mSlideContent.getRight(), mSlideContent.getBottom() + mSlideHeaderHeight);
    }

    private int mTouchSlop = 0;

    //private int mMinimumVelocity;
    //private int mMaximumVelocity;

    private float mInitialMotionX;
    private float mLastMotionY;

    private float mLastMotionX;
    private float mInitialMotionY;

    private float mAllScrollMotionY = 0;

    private int mSlideHeaderHeight = 0;

    private int mActivePointerId = -1;
    private boolean mIsBeingDrag = false;
    private static final int INVALID_POINTER = -1;

    private boolean mIsExpand = true;

    private VelocityTracker mVelocityTracker;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mAllScrollMotionY = 0;
                mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, 0);
                mInitialMotionY = mLastMotionY = MotionEventCompat.getY(ev, 0);
                break;

            case MotionEvent.ACTION_MOVE:
                final float currentY = MotionEventCompat.getY(ev, 0);
                final float deltaY = currentY - mInitialMotionY;

                mIsBeingDrag = isInterceptionTouch(deltaY);
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mIsBeingDrag = false;
                break;
        }

        return mIsBeingDrag;
    }

    private boolean isInterceptionTouch(float deltaY){
        if(deltaY < 0 && Math.abs(deltaY) > mTouchSlop && mIsExpand){
            return true;
        }else{
            if(deltaY > mTouchSlop && !mIsExpand &&  mSlideContent.getScrollY() == 0){
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();

        switch (action & MotionEventCompat.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                // Remember where the motion event started
                mLastMotionY = mInitialMotionY = MotionEventCompat.getY(event, 0);;
                mLastMotionX = mInitialMotionX = MotionEventCompat.getX(event, 0);;
                break;
            case MotionEvent.ACTION_MOVE:
                if (!mIsBeingDrag) {
                    return false;
                }

                if (mIsBeingDrag) {
                    final float y = MotionEventCompat.getY(event, 0);
                    final int deltaY = (int)((y - mLastMotionY));
                    mLastMotionY = y;

                    checkDrag(deltaY);
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                finishScroller();
                mIsBeingDrag = false;
                break;
            case MotionEventCompat.ACTION_POINTER_DOWN: {
                break;
            }
            case MotionEventCompat.ACTION_POINTER_UP:
                break;
        }

        return true;
    }

    private void checkDrag(int deltaY){
        int contentTop = mSlideContent.getTop();
        int headerTop = mSlideHeader.getTop();
        int headerBottom = mSlideHeader.getBottom();
        int parentTop = this.getTop();
        int parentPaddingTop = this.getPaddingTop();
        int limitContentTop = parentTop + parentPaddingTop;

        int headerDeltay = 0;
        int contentDeltay = 0;
        if(deltaY == 0)
            return;
        if(deltaY > 0) {
            int h_deltaY = (int)(deltaY * mHeaderSpeedRate);
            if ((headerTop + h_deltaY) > limitContentTop) {
                headerDeltay = limitContentTop - headerTop;
            } else {
                headerDeltay = h_deltaY;
            }
            mSlideHeader.offsetTopAndBottom(headerDeltay);

            if((contentTop + deltaY) > (headerBottom + headerDeltay)){
                contentDeltay = (headerBottom + headerDeltay) - contentTop;
            }else{
                contentDeltay = deltaY;
            }
            mAllScrollMotionY = contentDeltay;
            mSlideContent.offsetTopAndBottom(contentDeltay);
        }else{
            int h_deltaY = (int)(deltaY * mHeaderSpeedRate);
            if ((headerTop + h_deltaY) < (limitContentTop - mLimitHeaderHeight)) {
                headerDeltay = limitContentTop - mLimitHeaderHeight - headerTop;
            } else {
                headerDeltay = h_deltaY;
            }
            mSlideHeader.offsetTopAndBottom(headerDeltay);

            if((contentTop + deltaY) < (limitContentTop + mLimitContentHeight)){
                contentDeltay = limitContentTop + mLimitContentHeight - contentTop;
            }else{
                contentDeltay = deltaY;
            }
            mAllScrollMotionY = contentDeltay;
            mSlideContent.offsetTopAndBottom(contentDeltay);
        }
    }

    private void finishScroller(){
        int parentTop = this.getTop();
        int parentPaddingTop = this.getPaddingTop();
        int limitContentTop = parentTop + parentPaddingTop;
        int contentTop = mSlideContent.getTop();

        if(mAllScrollMotionY <= 0) {
            mLastScrollY = contentTop;
            //mScroller.startScroll(0, contentTop, 0, (limitContentTop - contentTop), 500);
            startAnimation(contentTop, limitContentTop);
            mIsExpand = false;
        }else{
            mLastScrollY = contentTop;
            int headerHeight = mSlideHeader.getHeight();
            limitContentTop += headerHeight;
//            mScroller.startScroll(0, contentTop, 0, (limitContentTop - contentTop), 500);
            startAnimation(contentTop, limitContentTop);
            mIsExpand = true;
        }
    }

    private int mLimitHeaderHeight = -1;
    private int mLimitContentHeight = -1;
    private double mHeaderSpeedRate = 0;
    private int mCurrentRow = 0;
    public void onEventMainThread(Message message){
        if(message.what == EventIndex.MODEL_TAG_INDEX){
            int k = message.arg1;
            mCurrentRow = k / 7;
            initLimitHeight();
        }
    }

    private void initLimitHeight(){
        mLimitContentHeight = (int) CalendarDraw.getDayHeight();
        mLimitHeaderHeight = mCurrentRow * (int)CalendarDraw.getDayHeight();
        mHeaderSpeedRate = mLimitHeaderHeight * 1.0 / (mSlideHeaderHeight - mLimitContentHeight);
        android.util.Log.i("zyw","mLimitHeaderHeight = " + mLimitHeaderHeight);
        android.util.Log.i("zyw","(mSlideHeaderHeight - mLimitContentHeight) = " + (mSlideHeaderHeight - mLimitContentHeight));
        android.util.Log.i("zyw","mHeaderSpeedRate = " + mHeaderSpeedRate);
    }

    private int mLastScrollY = 0;

    public interface SlideAssistant {

        public int slideSpeedForTop();

        public int slideSpeedForContent();

    }
}
